﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using smartcrm.Models;
using smartcrm.Utilities;
using System.Web.Script.Serialization;
using Newtonsoft.Json.Linq;
using System.Text;
using System.IO;
using MigraDoc.DocumentObjectModel;
using MigraDoc.Rendering;
using MigraDoc.DocumentObjectModel.Tables;

namespace smartcrm.Controllers
{
    [Authorization]
    public class OrderController : BaseController
    {
        [Authorization]
        [Permission(PermissionNo = "P0201")]
        public ActionResult Index(string so, string sb, string se, string sc, string ss, string sf, string page)
        {
            OrderList orders = new OrderList();

            PagerConfig pconfig = GetPagerConfig(page);
            orders.RouterDirectory.Add("so", so);            
            orders.RouterDirectory.Add("sb", sb);
            orders.RouterDirectory.Add("se", se);
            orders.RouterDirectory.Add("sc", sc);
            orders.RouterDirectory.Add("ss", ss);
            orders.RouterDirectory.Add("sf", sf);

            List<Customer> allCustomers = Context.Customer.ToList();
            orders.Orders = GetOrderList(so, sb, se, sc, ss, sf);

            orders.sc = sc;
            orders.sb = sb;
            orders.se = se;
            orders.ss = ss;
            orders.sf = sf;

            BindDdlAndTotal(orders);

            pconfig.TotalRecord = orders.Orders.Count;
            orders.Orders = orders.Orders.ToPagedList(pconfig.CurrentPage, pconfig.PageSize);

            orders.PagerConfig = pconfig;

            return View(orders);
        }

        [Authorization]
        [PermissionAttribute(PermissionNo = "P0206")]
        public ActionResult UnApprovedOrder()
        {
            OrderList orders = new OrderList();

            List<Customer> allCustomers = Context.Customer.ToList();
            orders.Orders = GetUnApprovedOrderList();

            return View(orders);
        }

        private void BindDdlAndTotal(OrderList orders)
        {
            orders.DdlCustomer = BindCustomerDdl();
            orders.DdlPaymentStatus = GetOrderPaymentStatusDdl();
            orders.DdlStatus = GetOrderStatusDdl();
            orders.DdlPaymentType = PaymentTypeDdl;
            orders.DdlFactory = BindFactoryDdl();
            CalculateTotal(orders);
        }

        private void CalculateTotal(OrderList orders)
        {
            foreach (OrderInfo o in orders.Orders)
            {
                if (!o.FactoryAmount.HasValue)
                {
                    o.FactoryAmount = 0;
                }
                if (!o.Paid.HasValue)
                {
                    o.Paid = 0;
                }
            }
            orders.TotalAmount = (float)orders.Orders.Sum(m => m.Amount);
            orders.TotalFactoryAmount = (float)orders.Orders.Sum(m => m.FactoryAmount);
            orders.TotalPaid = (float)orders.Orders.Sum(m => m.Paid);
            orders.TotalUnpaid = (float)orders.Orders.Sum(m => m.Amount - (m.Paid.HasValue ? m.Paid.Value : 0));
        }

        [HttpGet]
        [PermissionAttribute(PermissionNo = "P0202")]
        public ActionResult Create()
        {
            OrderModel model = new OrderModel();

            BindItemList(model);
            model.OrderNo = AUTO_NUMBER;
            model.IsAdd = "1";
            model.OrderTemplate = OrderTemplate;
            model.TransactionDateStr = DateTime.Now.ToString("yyyy-MM-dd");
            model.WorkFlowIsNull = "1";

            return View("Edit", model);
        }

        [PermissionAttribute(PermissionNo = "P0205", IsJson = true)]
        public JsonResult GetPaymentDetail(string OrderNo)
        {
            JsonResult result = new JsonResult();
            string errorMessage = string.Empty;

            Order order = Context.Order.FirstOrDefault(m => m.OrderNo == OrderNo);
            string paymentHistory = string.Empty;
            if (order == null)
            {
                result.Data = new { code = 1, message = MSG_NoEntityFound };
            }
            else
            {
                List<OrderPayment> payments = Context.OrderPayment.Where(m => m.OrderNo == order.OrderNo).ToList();

                foreach (OrderPayment p in payments)
                {
                    paymentHistory += string.Format("{0} {1} 支付金额：{2} 支付方式：{3}", p.CreateTime.ToString("yyyy-MM-dd HH:mm:ss"), p.Creator, p.Amount, p.PaymentType);
                    if (!string.IsNullOrEmpty(p.Memo))
                    {
                        paymentHistory += string.Format(" 备注:{0}", p.Memo);
                    }
                    paymentHistory += "<br/>";
                }
                if (string.IsNullOrEmpty(paymentHistory))
                {
                    paymentHistory = "无支付记录";
                }

                result.Data = new { code = 0, data = new { OrderNo = order.OrderNo, PaymentStatus = EnumHelper.GetEnumDescriptionByValue(typeof(OrderPaymentStatus), order.PaymentStatus), Amount = order.Amount, Paid = order.Paid, Unpaid = (float)Math.Round(order.Amount - (order.Paid.HasValue ? order.Paid.Value : 0), 2), PaymentHistory = paymentHistory, Css = order.PaymentStatus == ((int)OrderPaymentStatus.Paid).ToString() ? "OrderStatusPaid" : "OrderStatusUnPaid" } };
            }

            return result;

        }

        public JsonResult GetDetail(string OrderNo)
        {
            JsonResult result = new JsonResult();
            string errorMessage = string.Empty;

            OrderInfo detail = new OrderInfo();
            Order order = Context.Order.FirstOrDefault(m => m.OrderNo == OrderNo);
            if (order == null)
            {
                result.Data = new { code = 1, message = MSG_NoEntityFound };
            }
            else
            {
                detail.OrderNo = order.OrderNo;
                detail.OrderName = order.OrderName;
                detail.CustomerShortName = Context.Customer.First(m => m.CustomerNo == order.CustomerNo).CustomerShortName;
                detail.Contact = order.Contact;
                detail.Amount = order.Amount;
                detail.Paid = order.Paid;
                detail.FactoryAmount = order.FactoryAmount;
                detail.Creator = order.Creator;
                detail.Memo = order.Memo;
                detail.TransactionDateString = order.TransactionDate.ToString("yyyy-MM-dd");
                detail.CreatedTimeString = order.CreatedTime.ToString("yyyy-MM-dd HH:mm:ss");
                detail.CategoryName = order.CategoryName;
                detail.DetailText = order.DetailText;
                detail.OrderStatusNo = order.OrderStatusNo;
                detail.PaymentStatus = order.PaymentStatus;
                detail.Number = order.Number;
                detail.ExpectDeliveryDateString = order.ExpectDeliveryDate.HasValue ? order.ExpectDeliveryDate.Value.ToString("yyyy-MM-dd") : "";
                detail.StatusDescription = order.OrderStatus.StatusName;
                detail.PaymentStatusDescription = GetOrderPaymentStatusString(detail.PaymentStatus);
                detail.QueryURL = ORDER_QUERY_URL + order.OrderNo + order.QueryCode;

                if (order.PaymentStatus == ((int)OrderPaymentStatus.Unpaid).ToString() ||
                    order.PaymentStatus == ((int)OrderPaymentStatus.PartPaid).ToString())
                {
                    detail.Css = "OrderStatusUnPaid";
                }
                else
                {
                    detail.Css = "OrderStatusPaid";
                }

                detail.Detail += string.Format("{0}({1})", order.CategoryName, order.DetailText);

                if (order.Factory != null)
                {
                    detail.Detail += string.Format("<br/>加工商: {0}, ", order.Factory.FactoryName);
                    if (order.FactoryAmount.HasValue)
                    {
                        detail.Detail += string.Format("加工费: {0}", order.FactoryAmount);
                    }
                }

                List<OrderLog> logs = Context.OrderLog.Where(m => m.OrderNo == order.OrderNo).ToList();
                detail.History = string.Empty;
                foreach (OrderLog h in logs)
                {
                    detail.History += string.Format("{0} {1} {2}", h.LogDate.ToString("yyyy-MM-dd HH:mm:ss"), h.UserName, h.Operation);
                    detail.History += "<br/>";
                }

                List<OrderPayment> payments = Context.OrderPayment.Where(m => m.OrderNo == order.OrderNo).ToList();
                detail.Payment = string.Empty;
                foreach (OrderPayment p in payments)
                {
                    detail.Payment += string.Format("{0} {1} 支付金额：{2} 支付方式：{3}", p.CreateTime.ToString("yyyy-MM-dd HH:mm:ss"), p.Creator, p.Amount, p.PaymentType);
                    if (!string.IsNullOrEmpty(p.Memo))
                    {
                        detail.Payment += string.Format(" 备注:{0}", p.Memo);
                    }
                    detail.Payment += "<br/>";
                }

                detail.steps = new List<JSOrderWorkFlow>();
                List<OrderFlow> orderFlows = Context.OrderFlow.Where(m => m.OrderNo == OrderNo).OrderBy(m => m.OrderFlowNo).ToList();
                foreach (OrderFlow of in orderFlows)
                {
                    JSOrderWorkFlow wf = new JSOrderWorkFlow();
                    wf.StepName = of.WorkFlowStep.WorkFlowStepName;
                    wf.UserName = of.User == null ? "" : of.User.UserName;
                    wf.DateTime = of.EndDate.HasValue ? of.EndDate.Value.ToString("yyyy-MM-dd") : "";
                    wf.IsFinished = of.IsFinished;
                    detail.steps.Add(wf);
                }

                List<OrderAttachment> attachments = Context.OrderAttachment.Where(m => m.OrderNo == OrderNo).ToList();
                detail.Attachments = new List<SimpleItemList>();
                foreach (OrderAttachment o in attachments)
                {
                    detail.Attachments.Add(new SimpleItemList() { ItemText = o.FileName, ItemValue = o.AttachmentNo, Addition1 = o.FileTypeImage, Addition2 = string.Format("{0} {1}", o.Creator, o.Createtime.ToString("yyyy-MM-dd")) });
                }

                detail.OrderMemos = new List<SimpleItemList>();
                foreach (OrderMemo o in order.OrderMemo)
                {
                    detail.OrderMemos.Add(new SimpleItemList() { Addition1 = o.Memo, Addition2 = o.Creator, Addition3 = o.Createtime.ToString("yyyy-MM-dd") });
                }

                result.Data = new { code = 0, data = detail };
            }

            return result;

        }

        [HttpGet]
        [PermissionAttribute(PermissionNo = "P0203")]
        public ActionResult Edit(string OrderNo,string GoBackURL)
        {       
            if (string.IsNullOrEmpty(OrderNo))
            {
                return Redirect("/Order");
            }

            OrderModel model = new OrderModel();

            if (!string.IsNullOrEmpty(GoBackURL))
            {
                JsUrl jsUrl = new JavaScriptSerializer().Deserialize(GoBackURL, typeof(JsUrl)) as JsUrl;
                GoBackURL = GetUrl(jsUrl);                
            }

            model.BackURL = GoBackURL;
            Order order = Context.Order.Where(m => m.OrderNo == OrderNo).FirstOrDefault();
            model.BindFromOrderEntity(order);
            model.IsAdd = "0";

            if (order == null)
            {
                return Redirect("/Order");
            }


            BindItemList(model);
            model.TransactionDateStr = model.TransactionDate.ToString("yyyy-MM-dd");
            model.hContactNo = model.ContactNo;

            if (string.IsNullOrEmpty(order.WorkFlowNo))
            {
                model.WorkFlowIsNull = "1";
            }
            else
            {
                model.WorkFlowIsNull = "0";
            }

            return View(model);
        }

        [PermissionAttribute(PermissionNo = "P0205", IsJson = true)]
        public JsonResult PaymentAdd(string OrderNo, float PaymentAmount, string PaymentType, string PaymentMemo)
        {
            JsonResult result = new JsonResult();

            Order order = Context.Order.FirstOrDefault(m => m.OrderNo == OrderNo);
            if (order == null)
            {
                result.Data = new { code = 1, message = MSG_NoEntityFound };
            }
            else
            {
                if (order.Paid.HasValue && PaymentAmount > order.Amount - order.Paid.Value)
                {
                    result.Data = new { code = 1, message = "提交失败：支付金额大于未付金额" };
                }
                else
                {
                    OrderPayment payment = new OrderPayment();
                    payment.Amount = PaymentAmount;
                    payment.OrderNo = OrderNo;
                    payment.Creator = GetLoginUser().UserName;
                    payment.CreateTime = DateTime.Now;
                    payment.Memo = PaymentMemo;
                    payment.PaymentType = PaymentType;

                    order.Paid = (order.Paid.HasValue ? order.Paid.Value : 0) + PaymentAmount;
                    SetOrderPaymentStatus(order);
                    Context.OrderPayment.AddObject(payment);

                    Context.SaveChanges();

                    result.Data = new { code = 0 };
                }
            }

            return result;
        }

        [HttpPost]
        [PermissionAttribute(PermissionNo = "P0202", IsJson = true)]
        public JsonResult Add(string BasicInfo, string DetailInfo)
        {
            JsonResult result = new JsonResult();
            JavaScriptSerializer js = new JavaScriptSerializer();

            List<OrderDetailModel> details = js.Deserialize(DetailInfo, typeof(List<OrderDetailModel>)) as List<OrderDetailModel>;

            List<IdNumber> newNos = new List<IdNumber>();

            foreach (OrderDetailModel d in details)
            {
                Order order = js.Deserialize(BasicInfo, typeof(Order)) as Order;
                string newOrderNo = GetNewIdNumber(IdNumberType.Order);
                newNos.Add(new IdNumber() { Type = IdNumberType.Order,No = newOrderNo });
                order.OrderNo = newOrderNo;
                order.CompanyNo = CompanyNo;
                order.Creator = GetLoginUser().UserName;
                order.CreatedTime = DateTime.Now;
                order.IsActive = true;
                order.OrderTemplate = OrderTemplate;
                order.WorkFlowNo = d.WorkFlowNo;
                order.QueryCode = GetOrderQueryNo();
                order.Approved = true;

                SetOrderPaymentStatus(order);

                WorkFlowStep wfs = Context.WorkFlowStep.FirstOrDefault(m => m.WorkFlowStepNo == d.WorkFlowStepNo);
                if (wfs == null)
                {
                    order.OrderStatusNo = CompanyNo + ORDER_STATUS_CREATED;
                }
                else
                {
                    order.OrderStatusNo = wfs.StatusNo;
                }

                order.OrderName = d.Content;
                order.Category = d.Category;
                order.CategoryName = d.CategoryName;
                order.ReportCategory = d.ReportCategory;
                order.Detail = d.Detail;
                order.DetailText = string.IsNullOrEmpty(d.DetailText) ? "" : d.DetailText;
                order.Number = d.Number;
                order.Price = Math.Round(d.Price, 2);

                order.Amount = d.Amount;

                if (string.IsNullOrEmpty(d.FactoryNo))
                {
                    order.Factory = null;
                }
                else
                {
                    order.FactoryNo = d.FactoryNo;
                }

                if (d.FactoryAmount.HasValue)
                {
                    order.FactoryAmount = Math.Round(d.FactoryAmount.Value, 2);
                }
                if (d.FactoryPrice.HasValue)
                {
                    order.FactoryPrice = Math.Round(d.FactoryPrice.Value, 2);
                }
                order.Amount = Math.Round(order.Amount, 2);

                order.ExpectDeliveryDate = d.ExpectDeliveryDate;
                order.Memo = d.Memo;
                SetZeroToNull(order);

                Context.Order.AddObject(order);

                OrderLog log = new OrderLog();
                log.OrderNo = order.OrderNo;
                log.LogDate = DateTime.Now;
                log.IsPublic = true;
                log.Operation = "创建订单";
                log.UserName = GetLoginUser().UserName;
                Context.OrderLog.AddObject(log);

                OrderFlow of = new OrderFlow();
                string newOrderFlowNo = GetNewIdNumber(IdNumberType.OrderFlow);
                newNos.Add(new IdNumber(){No = newOrderFlowNo, Type = IdNumberType.OrderFlow});
                of.OrderFlowNo = newOrderFlowNo;
                of.OrderNo = order.OrderNo;
                of.WorkFlowNo = order.WorkFlowNo;
                of.WorkFlowStepNo = Context.WorkFlowStep.First(m => m.IsBeginPoint && m.CompanyNo == CompanyNo && m.WorkFlowNo == order.WorkFlowNo).WorkFlowStepNo;
                of.BeginDate = order.CreatedTime;
                of.EndDate = of.BeginDate;
                of.UserId = GetLoginUser().UserId;
                of.UserName = GetLoginUser().UserName;
                of.IsFinished = true;
                Context.OrderFlow.AddObject(of);

                of = new OrderFlow();
                newOrderFlowNo = GetNewIdNumber(IdNumberType.OrderFlow);
                newNos.Add(new IdNumber() { Type = IdNumberType.OrderFlow, No = newOrderFlowNo });
                of.OrderFlowNo = newOrderFlowNo;
                of.OrderNo = order.OrderNo;
                of.WorkFlowNo = order.WorkFlowNo;
                of.WorkFlowStepNo = d.WorkFlowStepNo;
                of.BeginDate = order.CreatedTime;
                if (!string.IsNullOrEmpty(d.WorkFlowUserId))
                {
                    of.UserId = d.WorkFlowUserId;
                    of.UserName = Context.User.First(m => m.UserId == d.WorkFlowUserId).UserName;
                }
                of.IsFinished = false;

                Context.OrderFlow.AddObject(of);
            }

            try
            {
                Context.SaveChanges();
                if (GetLoginUser().PermissionList.Contains("P0201"))
                {
                    result.Data = new { code = 0 };
                }
                else
                {
                    result.Data = new { code = 9 };
                }

            }
            catch (Exception ex)
            {
                PutbackNos(newNos);
                 
                throw ex;
            }

            return result;
        }

        public void SetZeroToNull(Order order)
        {
            if (order.FactoryPrice.HasValue && order.FactoryPrice.Value == 0)
            {
                order.FactoryPrice = null;
            }
            if (order.FactoryAmount.HasValue && order.FactoryAmount.Value == 0)
            {
                order.FactoryAmount = null;
            }
        }

        [HttpPost]
        [PermissionAttribute(PermissionNo = "P0203", IsJson = true)]
        public JsonResult Update(string BasicInfo, string DetailInfo)
        {
            JsonResult result = new JsonResult();
            JavaScriptSerializer js = new JavaScriptSerializer();
            Order order = js.Deserialize(BasicInfo, typeof(Order)) as Order;
            List<OrderDetailModel> details = js.Deserialize(DetailInfo, typeof(List<OrderDetailModel>)) as List<OrderDetailModel>;

            Order orignialOrder = Context.Order.Where(m => m.OrderNo == order.OrderNo).FirstOrDefault();
            List<IdNumber> newNos = new List<IdNumber>();
            if (orignialOrder == null)
            {
                result.Data = new { code = 1, message = MSG_NoEntityFound };
            }
            else
            {
                OrderDetailModel d = details[0];
                order.Amount = Math.Round(d.Amount, 2);
                if (d.FactoryAmount.HasValue)
                {
                    order.FactoryAmount = Math.Round(d.FactoryAmount.Value, 2);
                }
                else
                {
                    order.FactoryAmount = null;
                }

                OrderLog log = RecordOrderLog(orignialOrder, order);

                if (log != null)
                {
                    log.IsPublic = false;
                }

                orignialOrder.OrderName = d.Content;
                orignialOrder.CustomerNo = order.CustomerNo;
                orignialOrder.ContactNo = order.ContactNo;
                orignialOrder.Contact = order.Contact;
                orignialOrder.Amount = Math.Round(d.Amount, 2);
                orignialOrder.TransactionDate = order.TransactionDate;
                orignialOrder.Memo = d.Memo;
                orignialOrder.Price = Math.Round(d.Price, 2);
                orignialOrder.FactoryAmount = order.FactoryAmount;

                if (d.FactoryPrice.HasValue)
                {
                    orignialOrder.FactoryPrice = Math.Round(d.FactoryPrice.Value, 2);
                }
                else
                {
                    orignialOrder.FactoryPrice = null;
                }

                orignialOrder.OrderName = d.Content;
                orignialOrder.ExpectDeliveryDate = d.ExpectDeliveryDate;
                orignialOrder.Detail = d.Detail;
                orignialOrder.DetailText = d.DetailText;
                orignialOrder.Number = d.Number;
                orignialOrder.Category = d.Category;
                orignialOrder.CategoryName = d.CategoryName;
                orignialOrder.ReportCategory = d.ReportCategory;

                if (string.IsNullOrEmpty(orignialOrder.WorkFlowNo))
                {
                    OrderFlow of = new OrderFlow();
                    string newOrderFlowNo = GetNewIdNumber(IdNumberType.OrderFlow);
                    newNos.Add(new IdNumber(){Type= IdNumberType.OrderFlow, No = newOrderFlowNo});
                    of.OrderFlowNo = newOrderFlowNo;
                    of.OrderNo = order.OrderNo;
                    of.WorkFlowNo = d.WorkFlowNo;
                    of.WorkFlowStepNo = Context.WorkFlowStep.First(m => m.IsBeginPoint && m.CompanyNo == CompanyNo && m.WorkFlowNo == d.WorkFlowNo).WorkFlowStepNo;
                    of.BeginDate = DateTime.Now;
                    of.EndDate = of.BeginDate;
                    of.UserId = GetLoginUser().UserId;
                    of.UserName = GetLoginUser().UserName;
                    of.IsFinished = true;
                    Context.OrderFlow.AddObject(of);

                    of = new OrderFlow();
                    newOrderFlowNo = GetNewIdNumber(IdNumberType.OrderFlow);
                    newNos.Add(new IdNumber(){Type= IdNumberType.OrderFlow, No = newOrderFlowNo});
                    of.OrderFlowNo = newOrderFlowNo;
                    of.OrderNo = order.OrderNo;
                    of.WorkFlowNo = d.WorkFlowNo;
                    of.WorkFlowStepNo = d.WorkFlowStepNo;
                    of.BeginDate = DateTime.Now;
                    if (!string.IsNullOrEmpty(d.WorkFlowUserId))
                    {
                        of.UserId = d.WorkFlowUserId;
                        of.UserName = Context.User.First(m => m.UserId == d.WorkFlowUserId).UserName;
                    }

                    of.IsFinished = false;

                    Context.OrderFlow.AddObject(of);

                }

                orignialOrder.WorkFlowNo = d.WorkFlowNo;

                if (string.IsNullOrEmpty(d.FactoryNo))
                {
                    orignialOrder.FactoryNo = null;
                }
                else
                {
                    orignialOrder.FactoryNo = d.FactoryNo;
                }
                if (log != null)
                {
                    Context.OrderLog.AddObject(log);
                }

                SetZeroToNull(orignialOrder);
            }

            try
            {
                Context.SaveChanges();
                if (GetLoginUser().PermissionList.Contains("P0201"))
                {
                    result.Data = new { code = 0 };
                }
                else
                {
                    result.Data = new { code = 9 };
                } 

            }
            catch (Exception ex)
            {               
                    PutbackNos(newNos);               

                throw ex;
            }

            return result;
        }

        public JsonResult GetOrderDetail(string OrderNo)
        {
            JsonResult result = new JsonResult();
            result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;

            if (string.IsNullOrEmpty(OrderNo))
            {
                result.Data = new { code = 1, message = MSG_NoEntityFound };
            }
            else
            {
                List<JsonOrder> details = Context.Order.Where(m => m.OrderNo == OrderNo).Select(m => new JsonOrder
                {
                    OrderNo = m.OrderNo,
                    Content = m.OrderName,
                    Category = m.Category,
                    CategoryName = m.CategoryName,
                    ReportCategory = m.ReportCategory,
                    DetailString = m.Detail,
                    DetailText = m.DetailText,
                    Number = m.Number,
                    Price = m.Price,
                    Amount = m.Amount,
                    FactoryNo = m.FactoryNo,
                    FactoryAmount = m.FactoryAmount,
                    FactoryPrice = m.FactoryPrice,
                    WorkFlowNo = m.WorkFlowNo,
                    ExpectDeliveryDate = m.ExpectDeliveryDate,
                    Memo = m.Memo
                }).ToList();

                // Why need to deserialize the Detail field(string)?
                // If we not deserialize the Detail field, then here the string will be Jsonable(with \" to represent "), 
                // and later on the client side, the \ itself will be changed to \\, that lead to many \ after multiple edit.
                JavaScriptSerializer json = new JavaScriptSerializer();

                foreach (JsonOrder o in details)
                {
                    o.Detail = json.Deserialize<object>(o.DetailString);
                    o.DetailString = o.DetailString;

                }

                result.Data = new { code = 0, data = details };
            }

            return result;
        }

        public JsonResult AddOrderMemo(string OrderNo, string Memo)
        {
            JsonResult result = new JsonResult();

            Order order = Context.Order.FirstOrDefault(m => m.OrderNo == OrderNo && m.CompanyNo == CompanyNo);

            if (order == null)
            {
                result.Data = new { code = 1, message = MSG_NoEntityFound };
            }
            else
            {
                OrderMemo memo = new OrderMemo();
                string newNo = GetNewIdNumber(IdNumberType.OrderMemo);
                memo.MemoNo = newNo;
                memo.OrderNo = OrderNo;
                memo.Memo = Memo.Trim();
                memo.Createtime = DateTime.Now;
                memo.Creator = GetLoginUser().UserName;

                try
                {
                    Context.OrderMemo.AddObject(memo);
                    Context.SaveChanges();
                    result.Data = new { code = 0, data = new SimpleItemList() { Addition1 = memo.Memo, Addition2 = memo.Creator, Addition3 = memo.Createtime.ToString("yyyy-MM-dd") } };
                }
                catch (Exception ex)
                {
                    PutbackNo(newNo, IdNumberType.OrderMemo);
                    throw ex;
                }
            }

            return result;
        }

        private OrderLog RecordOrderLog(Order oldOrder, Order newOrder)
        {
            OrderLog log = new OrderLog();
            log.OrderNo = oldOrder.OrderNo;
            log.UserName = GetLoginUser().UserName;
            log.LogDate = DateTime.Now;
            log.Operation = string.Empty;

            if (oldOrder.Amount != newOrder.Amount)
            {
                log.Operation += string.Format("订单金额：{0}->{1}, ", oldOrder.Amount, newOrder.Amount);
            }

            if (oldOrder.FactoryAmount.HasValue && oldOrder.FactoryAmount.Value == 0)
            {
                oldOrder.FactoryAmount = null;
            }

            if (newOrder.FactoryAmount.HasValue && newOrder.FactoryAmount.Value == 0)
            {
                newOrder.FactoryAmount = null;
            }

            if (oldOrder.FactoryAmount != newOrder.FactoryAmount)
            {
                log.Operation += string.Format("加工费用：{0}->{1}, ", oldOrder.FactoryAmount.HasValue ? oldOrder.FactoryAmount.Value.ToString() : "NULL", newOrder.FactoryAmount.HasValue ? newOrder.FactoryAmount.Value.ToString() : "NULL");
            }

            if (log.Operation.Length > 0)
            {
                log.Operation = log.Operation.Substring(0, log.Operation.Length - 2);
                return log;
            }
            else
            {
                return null;
            }
        }

        [HttpPost]
        [PermissionAttribute(PermissionNo = "P0204", IsJson = true)]
        public JsonResult Delete(string OrderNumber)
        {
            JsonResult result = new JsonResult();
            string errorMessage = string.Empty;

            Order OriginalOrder = Context.Order.FirstOrDefault(m => m.OrderNo == OrderNumber);
            if (OriginalOrder == null)
            {
                result.Data = new { code = 1, message = MSG_NoEntityFound };
            }
            else if (IS_DEMO)
            {
                result.Data = new { code = 1, message = MSG_IsDemo };
            }
            else
            {
                OriginalOrder.IsActive = false;
                Context.SaveChanges();
                result.Data = new { code = 0 };
            }

            return result;
        }

        public JsonResult GetContact(string CustomerNo)
        {
            JsonResult result = new JsonResult();
            result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;

            result.Data = Context.Contact.Where(m => m.CustomerNo == CustomerNo).Select(m => new { Id = m.ContactNo, Name = m.ContactName, Phone = (String.IsNullOrEmpty(m.Mobile) ? "" : m.Mobile) + (String.IsNullOrEmpty(m.Phone) ? "" : " " + m.Phone) }).ToList();
            return result;
        }

        private void BindItemList(OrderModel model)
        {
            model.DdlCustomer = BindCustomerDdl();
            model.DdlFactory = BindFactoryDdl();
            model.DdlPaymentType = PaymentTypeDdl;
            model.DdlOrderStatus = GetOrderPaymentStatusDdl();
            model.DdlWorkFlow = BindWorkFlowDdl();
        }

        [PermissionAttribute(PermissionNo = "P0301")]
        public ActionResult CustomerStatement(string sb, string se, string sc)
        {
            CustomerStatement orders = new CustomerStatement();

            List<Customer> allCustomers = Context.Customer.ToList();

            if (string.IsNullOrEmpty(sb) || string.IsNullOrEmpty(se))
            {
                orders.Orders = new List<OrderInfo>();
            }
            else
            {
                orders.Orders = GetOrderList(null, sb, se, sc, null, null);
            }

            BindDdlAndTotal(orders);

            orders.TotalUnpaid = (float)orders.Orders.Sum(m => m.Amount - (m.Paid.HasValue ? m.Paid.Value : 0));
            return View(orders);
        }

        [PermissionAttribute(PermissionNo = "P0302")]
        public ActionResult FactoryStatement(string sb, string se, string sf)
        {
            FactoryStatement orders = new FactoryStatement();

            List<Customer> allCustomers = Context.Customer.ToList();

            if (string.IsNullOrEmpty(sb) || string.IsNullOrEmpty(se))
            {
                orders.Orders = new List<OrderInfo>();
            }
            else
            {
                orders.Orders = GetOrderListByFactory(sb, se, sf);
                if (!string.IsNullOrEmpty(sf))
                {
                    Factory f = Context.Factory.FirstOrDefault(m => m.FactoryNo == sf);
                }
            }

            orders.TotalAmount = orders.Orders.Sum(m => m.FactoryAmount).Value;
            orders.DdlFactory = BindFactoryDdl();

            return View(orders);
        }

        private List<OrderInfo> GetOrderListByFactory(string sb, string se, string sf)
        {
            List<OrderInfo> result;

            IQueryable<OrderInfo> query;
            query = (from o in Context.Order.Where(m => m.IsActive && m.CompanyNo == CompanyNo && m.Approved)
                     select new OrderInfo
                     {
                         OrderNo = o.OrderNo,
                         CreatedTime = o.CreatedTime,
                         CustomerShortName = o.Customer.CustomerShortName,
                         OrderName = o.OrderName,
                         Contact = o.Contact,
                         Amount = o.Amount,
                         Paid = o.Paid,
                         PaymentStatus = o.PaymentStatus,
                         TransactionDate = o.TransactionDate,
                         CustomerNo = o.CustomerNo,
                         FactoryAmount = o.FactoryAmount,
                         FactoryNo = o.FactoryNo,
                         Number = o.Number,
                         Price = o.Price,
                         CategoryName = o.CategoryName,
                         DetailText = o.DetailText,
                         FactoryName = o.Factory == null ? "" : o.Factory.FactoryName
                     });



            if (!string.IsNullOrEmpty(sf))
            {
                query = query.Where(m => m.FactoryNo == sf);
            }

            if (!string.IsNullOrEmpty(sb))
            {
                DateTime startDate = DateTime.Parse(sb);
                query = query.Where(m => m.TransactionDate >= startDate);
            }

            if (!string.IsNullOrEmpty(se))
            {
                DateTime endDate = DateTime.Parse(se);
                endDate = endDate.AddDays(1);
                endDate = endDate.AddMilliseconds(-1);
                query = query.Where(m => m.TransactionDate <= endDate);
            }

            result = query.ToList();

            return result;
        }

        private List<OrderInfo> GetUnApprovedOrderList()
        {
            List<OrderInfo> result;
            IQueryable<OrderInfo> query = (from o in Context.Order.Where(m => m.IsActive && m.CompanyNo == CompanyNo && !m.Approved)
                                           select new OrderInfo
                                           {
                                               OrderNo = o.OrderNo,
                                               CreatedTime = o.CreatedTime,
                                               CustomerShortName = o.Customer.CustomerShortName,
                                               OrderName = o.OrderName,
                                               Contact = o.Contact,
                                               Amount = o.Amount,
                                               Paid = o.Paid,
                                               PaymentStatus = o.PaymentStatus,
                                               TransactionDate = o.TransactionDate,
                                               CustomerNo = o.CustomerNo,
                                               FactoryPrice = o.FactoryPrice,
                                               FactoryAmount = o.FactoryAmount,
                                               DetailText = o.DetailText,
                                               Category = o.Category,
                                               CategoryName = o.CategoryName,
                                               Number = o.Number,
                                               FactoryNo = o.FactoryNo,
                                               OrderStatusNo = o.OrderStatusNo,
                                               StatusDescription = o.OrderStatus.StatusName
                                           });
            result = query.ToList();
            return result;
        }

        private List<OrderInfo> GetOrderList(string so, string sb, string se, string sc, string ss, string sf)
        {
            List<OrderInfo> result;
            IQueryable<OrderInfo> query = (from o in Context.Order.Where(m => m.IsActive && m.CompanyNo == CompanyNo && m.Approved)
                                           select new OrderInfo
                                           {
                                               OrderNo = o.OrderNo,
                                               CreatedTime = o.CreatedTime,
                                               CustomerShortName = o.Customer.CustomerShortName,
                                               OrderName = o.OrderName,
                                               Contact = o.Contact,
                                               Amount = o.Amount,
                                               Paid = o.Paid,
                                               PaymentStatus = o.PaymentStatus,
                                               TransactionDate = o.TransactionDate,
                                               CustomerNo = o.CustomerNo,
                                               FactoryPrice = o.FactoryPrice,
                                               FactoryAmount = o.FactoryAmount,
                                               DetailText = o.DetailText,
                                               Category = o.Category,
                                               CategoryName = o.CategoryName,
                                               Number = o.Number,
                                               FactoryNo = o.FactoryNo,
                                               OrderStatusNo = o.OrderStatusNo,
                                               StatusDescription = o.OrderStatus.StatusName
                                           });


            if (!string.IsNullOrEmpty(sb))
            {
                DateTime startDate = DateTime.Parse(sb);
                query = query.Where(m => m.TransactionDate >= startDate);
            }

            if (!string.IsNullOrEmpty(se))
            {
                DateTime endDate = DateTime.Parse(se);
                endDate = endDate.AddDays(1);
                endDate = endDate.AddMilliseconds(-1);
                query = query.Where(m => m.TransactionDate <= endDate);
            }

            if (!string.IsNullOrEmpty(sc))
            {
                query = query.Where(m => m.CustomerNo == sc);
            }

            if (!string.IsNullOrEmpty(ss))
            {
                query = query.Where(m => m.PaymentStatus == ss);
            }

            if (!string.IsNullOrEmpty(so))
            {
                query = query.Where(m => m.OrderStatusNo == so);
            }

            if (!string.IsNullOrEmpty(sf))
            {
                query = query.Where(m => m.FactoryNo == sf);
            }

            result = query.ToList();
            foreach (OrderInfo i in result)
            {
                i.PaymentStatusDescription = GetOrderPaymentStatusString(i.PaymentStatus);
                i.Unpaid = Math.Round(i.Amount - (i.Paid.HasValue ? i.Paid.Value : 0), 2);
            }

            return result;
        }

        [PermissionAttribute(PermissionNo = "P0301")]
        public ActionResult GetCustomerStatementPdf(string sb, string se, string sc)
        {
            CustomerStatement orders = new CustomerStatement();
            orders.Orders = GetOrderList(null, sb, se, sc, null, null);
            CalculateTotal(orders);

            string content = System.IO.File.ReadAllText(Path.Combine(TEMPLATE_PATH, "CustomerStatement.html"));
            content = ReportCommonInfo(content, sb, se);

            PdfHelper helper = new PdfHelper();

            if (string.IsNullOrEmpty(sc))
            {
                content = content.Replace("{{{DIVCUSTOMER}}}", "none");
                content = content.Replace("{{{THCUSTOMER}}}", "");
            }
            else
            {
                content = content.Replace("{{{DIVCUSTOMER}}}", "block");
                content = content.Replace("{{{THCUSTOMER}}}", "display:none");
                content = content.Replace("{{{CUSTOMER_NAME}}}", Context.Customer.First(m => m.CustomerNo == sc).CustomerShortName);
            }

            content = content.Replace("{{{TOTAL_AMOUNT}}}", string.Format("{0:N2}", orders.TotalAmount));
            content = content.Replace("{{{TOTAL_PAID}}}", string.Format("{0:N2}", orders.TotalPaid));
            content = content.Replace("{{{TOTAL_UNPAID}}}", string.Format("{0:N2}", orders.TotalUnpaid));

            StringBuilder orderContent = new StringBuilder();
            foreach (OrderInfo order in orders.Orders)
            {
                orderContent.Append("<tr>");

                if (string.IsNullOrEmpty(sc))
                {
                    orderContent.Append(string.Format("<td>{0}</td>", order.CustomerShortName));
                }

                orderContent.Append(string.Format("<td>{0}</td>", order.TransactionDate.ToString("yyyy-MM-dd")));
                orderContent.Append(string.Format("<td>{0}</td>", order.OrderName));
                orderContent.Append(string.Format("<td>{0}</td>", order.CategoryName));
                orderContent.Append(string.Format("<td>{0}</td>", order.Number));
                orderContent.Append(string.Format("<td  class='amount'>{0}</td>", string.Format("{0:N2}", order.Amount)));
                orderContent.Append(string.Format("<td  class='amount'>{0}</td>", string.Format("{0:N2}", order.Paid)));
                orderContent.Append(string.Format("<td  class='amount'>{0}</td>", string.Format("{0:N2}", order.Unpaid)));
                orderContent.Append(string.Format("<td>{0}</td>", order.DetailText));
                orderContent.Append("</tr>");
            }
            content = content.Replace("{{{ORDER_CONTENT}}}", orderContent.ToString());
            string tempFileName = string.Format("{0}{1}", CompanyNo, DateTime.Now.ToString("yyyyMMddHHmmssfff"));
            tempFileName = Path.Combine(FILE_GENERATION_PATH, tempFileName);
            string tempHtmlFileName = string.Format("{0}{1}", tempFileName, ".html");
            string tempPdfFileName = string.Format("{0}{1}", tempFileName, ".pdf");
            StreamWriter write = new StreamWriter(tempHtmlFileName);
            write.Write(content);
            write.Close();

            helper.WKHtmlToPdf(tempHtmlFileName, tempPdfFileName, true);

            string pdfFileName = string.Format("对账单_{0}_{1}_{2}.pdf", CompanyNo, sb, se);
            Response.Clear();
            Response.ContentType = "application/pdf";
            Response.AppendHeader("Content-disposition", "attachment; filename=" + pdfFileName); // open in a new window

            return File(tempPdfFileName, "application/pdf");
        }

        [PermissionAttribute(PermissionNo = "P0302")]
        public ActionResult GetFactoryStatementPdf(string sb, string se, string sf)
        {
            FactoryStatement orders = new FactoryStatement();
            orders.Orders = GetOrderListByFactory(sb, se, sf);
            orders.TotalAmount = (float)orders.Orders.Sum(m => m.FactoryAmount);

            string content = System.IO.File.ReadAllText(Path.Combine(TEMPLATE_PATH, "FactoryStatement.html"));

            content = ReportCommonInfo(content, sb, se);

            PdfHelper helper = new PdfHelper();

            if (string.IsNullOrEmpty(sf))
            {
                content = content.Replace("{{{DIVFACTORY}}}", "none");
                content = content.Replace("{{{THFACTORY}}}", "");
            }
            else
            {
                content = content.Replace("{{{DIVFACTORY}}}", "block");
                content = content.Replace("{{{THFACTORY}}}", "display:none");
                content = content.Replace("{{{FACTORY_NAME}}}", Context.Factory.First(m => m.FactoryNo == sf).FactoryName);
            }

            content = content.Replace("{{{TOTAL_AMOUNT}}}", string.Format("{0:N2}", orders.TotalAmount));

            StringBuilder orderContent = new StringBuilder();
            foreach (OrderInfo order in orders.Orders)
            {
                orderContent.Append("<tr>");
                if (string.IsNullOrEmpty(sf))
                {
                    orderContent.Append(string.Format("<td>{0}</td>", order.FactoryName));
                }
                orderContent.Append(string.Format("<td>{0}</td>", order.TransactionDate.ToString("yyyy-MM-dd")));
                orderContent.Append(string.Format("<td>{0}</td>", order.OrderName));
                orderContent.Append(string.Format("<td>{0}</td>", order.CategoryName));
                orderContent.Append(string.Format("<td>{0}</td>", order.Number));
                orderContent.Append(string.Format("<td  class='amount'>{0}</td>", string.Format("{0:N2}", order.FactoryAmount)));
                orderContent.Append(string.Format("<td>{0}</td>", order.DetailText));
                orderContent.Append("</tr>");
            }

            content = content.Replace("{{{ORDER_CONTENT}}}", orderContent.ToString());

            string tempFileName = string.Format("{0}{1}", CompanyNo, DateTime.Now.ToString("yyyyMMddHHmmssfff"));
            tempFileName = Path.Combine(FILE_GENERATION_PATH, tempFileName);
            string tempHtmlFileName = string.Format("{0}{1}", tempFileName, ".html");
            string tempPdfFileName = string.Format("{0}{1}", tempFileName, ".pdf");
            StreamWriter write = new StreamWriter(tempHtmlFileName);
            write.Write(content);
            write.Close();

            helper.WKHtmlToPdf(tempHtmlFileName, tempPdfFileName, true);

            string pdfFileName = string.Format("对账单_{0}_{1}_{2}.pdf", CompanyNo, sb, se);
            Response.Clear();
            Response.ContentType = "application/pdf";
            Response.AppendHeader("Content-disposition", "attachment; filename=" + pdfFileName); // open in a new window

            return File(tempPdfFileName, "application/pdf");
        }

        private string ReportCommonInfo(string content, string sb, string se)
        {
            PdfCompanyInformation companyInfo = new PdfCompanyInformation();
            Company company = Context.Company.FirstOrDefault(m => m.CompanyNo == CompanyNo);

            companyInfo.Address = company.AddressOnReport;
            companyInfo.LogoPath = company.LogoOnReport;
            companyInfo.PhoneFax = company.PhoneFaxOnReport;
            companyInfo.PostCode = company.PostcodeOnReport;
            companyInfo.Name = company.CompanyNameOnReport;

            content = content.Replace("{{{LOGO_PATH}}}", LOGO_PATH);
            content = content.Replace("{{{COMPANY_LOGO}}}", companyInfo.LogoPath);
            content = content.Replace("{{{COMPANY_NAME}}}", companyInfo.Name);
            content = content.Replace("{{{COMPANY_ADDRESS}}}", companyInfo.Address);
            content = content.Replace("{{{COMPANY_POSTCODE}}}", companyInfo.PostCode);
            content = content.Replace("{{{COMPANY_PHONE_FAX}}}", companyInfo.PhoneFax);

            content = content.Replace("{{{START_END_TIME}}}", string.Format("{0} 至 {1}", sb, se));
            content = content.Replace("{{{CREATE_DATE}}}", DateTime.Now.Date.ToString("yyyy-MM-dd"));

            return content;
        }

        public JsonResult GetWorkFlowNextSteps(string WorkFlowNo, string WorkFlowStepNo)
        {
            JsonResult result = new JsonResult();
            result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;

            WorkFlow wf = Context.WorkFlow.FirstOrDefault(m => m.CompanyNo == CompanyNo && m.WorkFlowNo == WorkFlowNo);
            if (wf == null)
            {
                result.Data = new { code = 1, message = MSG_NoEntityFound };
            }
            else
            {
                List<SimpleItemList> steps = new List<SimpleItemList>();
                WorkFlowStep step;
                if (WorkFlowStepNo == "0")  // Order just created.
                {
                    step = Context.WorkFlowStep.FirstOrDefault(m => m.WorkFlowNo == WorkFlowNo && m.IsBeginPoint);
                }
                else
                {
                    step = Context.WorkFlowStep.FirstOrDefault(m => m.WorkFlowNo == WorkFlowNo && m.WorkFlowStepNo == WorkFlowStepNo);
                }

                if (step == null)
                {
                    result.Data = new { code = 1, message = MSG_NoEntityFound };
                }
                else
                {
                    if (!string.IsNullOrEmpty(step.FollowupSteps))
                    {
                        string[] stepNos = step.FollowupSteps.Split(',');
                        steps = Context.WorkFlowStep.Where(m => stepNos.Contains(m.WorkFlowStepNo)).Select(m => new SimpleItemList { ItemValue = m.WorkFlowStepNo, ItemText = m.WorkFlowStepName }).ToList();
                    }

                    result.Data = new { code = 0, data = steps };
                }
            }

            return result;
        }

        public JsonResult GetWorkFlowStepUsers(string WorkFlowStepNo)
        {
            JsonResult result = new JsonResult();
            result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;

            List<SimpleItemList> users = new List<SimpleItemList>();
            WorkFlowStep step;
            step = Context.WorkFlowStep.FirstOrDefault(m => m.WorkFlowStepNo == WorkFlowStepNo);

            if (step == null)
            {
                result.Data = new { code = 1, message = MSG_NoEntityFound };
            }
            else
            {
                if (!string.IsNullOrEmpty(step.UserIds))
                {
                    string[] userIds = step.UserIds.Split(',');
                    users = Context.User.Where(m => userIds.Contains(m.UserId)).Select(m => new SimpleItemList { ItemValue = m.UserId, ItemText = m.UserName }).ToList();
                }

                result.Data = new { code = 0, data = users, isEndPoint = step.IsEndPoint ? "1" : "0" };
            }

            return result;
        }

        public JsonResult GetOrderNextStep(string OrderNo)
        {
            JsonResult result = new JsonResult();
            result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;

            OrderFlow of = Context.OrderFlow.FirstOrDefault(m => m.IsFinished == false && m.OrderNo == OrderNo && m.WorkFlowStep.WorkFlow.CompanyNo == CompanyNo);
            JSOrderNextStep model = new JSOrderNextStep();

            if (of == null)
            {
                result.Data = new { code = 1, message = MSG_NoEntityFound };
            }
            else
            {
                WorkFlowStep step = of.WorkFlowStep;

                List<SimpleItemList> steps = new List<SimpleItemList>();

                if (!string.IsNullOrEmpty(step.FollowupSteps))
                {
                    string[] stepNos = step.FollowupSteps.Split(',');
                    model.FollowUps = Context.WorkFlowStep.Where(m => stepNos.Contains(m.WorkFlowStepNo)).Select(m => new SimpleItemList { ItemValue = m.WorkFlowStepNo, ItemText = m.WorkFlowStepName }).ToList();
                }
                model.IsEndPoint = step.IsEndPoint;

                if (!string.IsNullOrEmpty(step.UserIds))
                {
                    string[] Nos = step.UserIds.Split(',');
                    model.TeamUserIds = Context.User.Where(m => Nos.Contains(m.UserId)).Select(m => new SimpleItemList { ItemValue = m.UserId, ItemText = m.UserName }).ToList();
                    SimpleItemList selfUser = model.TeamUserIds.FirstOrDefault(m => m.ItemValue == GetLoginUser().UserId);
                    if (selfUser != null)
                    {
                        model.TeamUserIds.Remove(selfUser);
                    }
                }

                result.Data = new { code = 0, data = model };
            }

            return result;
        }

        public JsonResult OrderFlowToNext(string OrderNo, string WorkFlowStepNo, string UserId, string NextType)
        {
            JsonResult result = new JsonResult();
            string newNo = string.Empty;
            bool error = false;
            Order order = Context.Order.FirstOrDefault(m => m.OrderNo == OrderNo && m.CompanyNo == CompanyNo);
            OrderFlow currentOF = Context.OrderFlow.FirstOrDefault(m => m.IsFinished == false && m.OrderNo == order.OrderNo);
            if (order == null || currentOF == null)
            {
                error = true;
            }
            else if (NextType == "1")
            {
                currentOF.IsFinished = true;
                currentOF.EndDate = DateTime.Now;

                WorkFlowStep step = Context.WorkFlowStep.FirstOrDefault(m => m.WorkFlowStepNo == WorkFlowStepNo);
                if (step == null)
                {
                    error = true;
                }
                else
                {
                    order.OrderStatusNo = step.StatusNo;
                    OrderFlow of = new OrderFlow();
                    newNo = GetNewIdNumber(IdNumberType.OrderFlow);
                    of.OrderFlowNo = newNo;
                    of.OrderNo = OrderNo;
                    of.WorkFlowNo = order.WorkFlowNo;
                    of.WorkFlowStepNo = WorkFlowStepNo;
                    of.BeginDate = DateTime.Now;
                    if (step.IsEndPoint)
                    {
                        of.EndDate = of.BeginDate;
                        of.IsFinished = true;
                        of.UserId = GetLoginUser().UserId;
                        of.UserName = GetLoginUser().UserName;
                    }
                    else
                    {
                        of.UserId = UserId;
                        User user = Context.User.FirstOrDefault(m => m.UserId == UserId);
                        if (user == null)
                        {
                            error = true;
                        }
                        else
                        {
                            of.UserName = user.UserName;
                        }
                        of.IsFinished = false;
                    }
                    Context.OrderFlow.AddObject(of);
                }
            }
            else
            {
                User user = Context.User.FirstOrDefault(m => m.UserId == UserId);
                if (currentOF == null || user == null)
                {
                    error = true;
                }
                else
                {
                    currentOF.UserId = UserId;
                    currentOF.UserName = user.UserName;
                    OrderLog log = new OrderLog();
                    log.IsPublic = true;
                    log.OrderNo = OrderNo;
                    log.UserName = GetLoginUser().UserName;
                    log.Operation = string.Format("任务 [{0}] 转移给 [{1}]", currentOF.WorkFlowStep.WorkFlowStepName, user.UserName);
                    log.LogDate = DateTime.Now;
                    Context.OrderLog.AddObject(log);
                }
            }

            try
            {
                Context.SaveChanges();
            }
            catch (Exception ex)
            {
                PutbackNo(newNo, IdNumberType.OrderFlow);
                
                throw ex;
            }

            if (error)
            {
                result.Data = new { code = 1, message = MSG_NoEntityFound };
            }
            else
            {
                result.Data = new { code = 0 };
            }

            return result;
        }

        public JsonResult FileUpload(HttpPostedFileBase fileToUpload, string OrderNo)
        {
            JsonResult result = new JsonResult();
            AttachmentConfig config = AttachmentConfigurate;
            string fileRealName = string.Empty;
            string fileExtension = Path.GetExtension(fileToUpload.FileName).Replace(".", "").ToLower();
            if (fileToUpload == null)
            {
                result.Data = new { code = 1, message = "文件不存在" };
            }
            else
            {
                string fileName = Path.Combine(config.RootPath, CompanyNo);
                fileName = Path.Combine(fileName, OrderNo);
                if (!Directory.Exists(fileName))
                {
                    try
                    {
                        Directory.CreateDirectory(fileName);
                    }
                    catch
                    {
                        result.Data = new { code = 1 };
                    }
                }

                fileRealName = Path.GetFileName(fileToUpload.FileName);
                if (fileToUpload.ContentLength > 1024 * 1024 * config.SizeLimitation)
                {
                    result.Data = new { code = 1, message = "文件大小超过限制" };
                }
                else if (fileExtension == ".exe" || fileExtension == ".bat" || fileExtension == ".msi")
                {
                    result.Data = new { code = 1, message = "文件类型不允许" };
                }
                else
                {
                    string fileNo = GetNewIdNumber(IdNumberType.OrderAttachment);
                    fileName = Path.Combine(fileName, fileNo + Path.GetExtension(fileToUpload.FileName));
                    try
                    {
                        fileToUpload.SaveAs(fileName);

                        OrderAttachment attachment = new OrderAttachment();
                        attachment.AttachmentNo = fileNo;
                        attachment.OrderNo = OrderNo;
                        attachment.FileName = fileRealName;
                        attachment.FilePath = fileName;
                        attachment.Createtime = DateTime.Now;
                        attachment.Creator = GetLoginUser().UserName;
                        attachment.UploadByCustomer = false;

                        if (System.IO.File.Exists(Path.Combine(Server.MapPath("/"), @"Images\filetype\" + fileExtension + ".gif")))
                        {
                            attachment.FileTypeImage = "/Images/filetype/" + fileExtension + ".gif";
                        }
                        else
                        {
                            attachment.FileTypeImage = "/Images/filetype/" + "unknown.gif";
                        }

                        Context.OrderAttachment.AddObject(attachment);
                        Context.SaveChanges();

                        result.Data = new { code = 0, fileName = fileRealName, fileNo = fileNo };
                    }
                    catch (Exception ex)
                    {
                        PutbackNo(fileNo, IdNumberType.OrderAttachment);
                        throw ex;
                    }
                }
            }
            return Json(result, "text/plain;charset=UTF-8");
        }

        public JsonResult GetOrderAttachments(string OrderNo)
        {
            JsonResult result = new JsonResult();
            result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
            Order order = Context.Order.FirstOrDefault(m => m.OrderNo == OrderNo && m.CompanyNo == CompanyNo);
            if (order == null)
            {
                result.Data = new { code = 1 };
            }
            else
            {
                List<SimpleItemList> attachments = Context.OrderAttachment.Where(m => m.OrderNo == OrderNo).Select(m => new SimpleItemList() { ItemText = m.FileName, ItemValue = m.AttachmentNo, Addition1 = m.FileTypeImage, Addition2 = m.Creator }).ToList();
                result.Data = new { code = 0, data = attachments };
            }
            return result;
        }

        [PermissionAttribute(PermissionNo = "P0206", IsJson = true)]
        public JsonResult Approve(string OrderNo)
        {
            JsonResult result = new JsonResult();
            result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
            Order order = Context.Order.FirstOrDefault(m => m.OrderNo == OrderNo && m.CompanyNo == CompanyNo);
            if (order == null)
            {
                result.Data = new { code = 1 };
            }
            else if (order.Approved)
            {
                result.Data = new { code = 1, message = "操作失败：订单已经被他人审核。" };
            }
            else if (string.IsNullOrEmpty(order.WorkFlowNo))
            {
                result.Data = new { code = 1, message = "操作失败：请先为订单设置流程。" };
            }
            else if (order.Price == 0 && order.Amount == 0)
            {
                result.Data = new { code = 1, message = "操作失败：请先为订单设置单价和金额。" };
            }
            else
            {
                order.Approved = true;

                Context.SaveChanges();
                result.Data = new { code = 0 };
            }
            return result;
        }


        public JsonResult DeleteAttachment(string OrderNo, string FileNo)
        {
            JsonResult result = new JsonResult();
            result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
            Order order = Context.Order.FirstOrDefault(m => m.OrderNo == OrderNo && m.CompanyNo == CompanyNo);
            if (order == null)
            {
                result.Data = new { code = 1, message = MSG_NoEntityFound };
            }
            else
            {
                OrderAttachment attachment = Context.OrderAttachment.FirstOrDefault(m => m.OrderNo == OrderNo && m.AttachmentNo == FileNo);
                if (attachment == null)
                {
                    result.Data = new { code = 1, message = MSG_NoEntityFound };
                }
                else
                {
                    Context.OrderAttachment.DeleteObject(attachment);
                    OrderLog log = new OrderLog();
                    log.OrderNo = OrderNo;
                    log.IsPublic = true;
                    log.UserName = GetLoginUser().UserName;
                    log.Operation = string.Format("删除附件:{0}", attachment.FileName);
                    log.LogDate = DateTime.Now;
                    Context.OrderLog.AddObject(log);
                    try
                    {
                        Context.SaveChanges();
                        result.Data = new { code = 0, FileNo = attachment.AttachmentNo };
                    }
                    catch
                    {
                        result.Data = new { code = 1 };
                    }
                    try
                    {
                        System.IO.File.Delete(attachment.FilePath);
                    }
                    catch
                    {
                        AddErrorMessage(string.Format("删除附件失败:{0}", attachment.FilePath));
                    }
                }

            }
            return result;
        }

        public ActionResult DownLoadAttachment(string FileNo)
        {
            OrderAttachment attachment = Context.OrderAttachment.FirstOrDefault(m => m.AttachmentNo == FileNo);
            if (attachment == null || attachment.Order.CompanyNo != CompanyNo)
            {
                throw new NoEntityFound();
            }
            else
            {
                Response.Clear();
                Response.ContentType = "application/octet-stream";// "application/ms-excel/msword";
                Response.AppendHeader("Content-disposition", "attachment; filename=" + attachment.FileName); // open in a new window
                return File(attachment.FilePath, "application / octet - stream");
            }
        }
    }
}
